package com.tvsinfo.jdk.demo.case9_fature;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * JDK8组合式Future
 *
 * @Author ruyi.song
 * @Date 2019/12/30 18:16:32
 */
public class Future2_V8_completable {

    public static void main(String[] args) {
        Future2_V8_completable future2_v8_completable = new Future2_V8_completable();
        future2_v8_completable.demo2_join().forEach(cfResult -> System.out.println(cfResult.getCfParameter()));
        future2_v8_completable.demo3_get().forEach(cfResult -> {
            if (cfResult != null) {
                System.out.println(cfResult.getCfParameter());
            } else {
                System.out.println("结果null");
            }
        });


    }

    /**
     * 测试1
     */
    void createCompletable() {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("starting......");
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("id:" + Thread.currentThread().getId() + " , name:" + Thread.currentThread().getName());
            return "finish .......";
        });
        try {
            System.out.println(completableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    List<CFResultA> demo2_join() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<CompletableFuture<CFResultA>> completableFutures = list.stream()
                .map(integer -> {
                    CompletableFuture<CFResultA> completableFuture = CompletableFuture.supplyAsync(() -> {
                        System.out.println("处理中......" + integer);
                        try {
                            Thread.sleep(3000L);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        CFResultB cfResultB = new CFResultB(integer);
                        return new CFResultA(integer, cfResultB);
                    });
                    return completableFuture;
                })
                .collect(Collectors.toList());
        //结果整理 CompletableFuture::join
        return completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
    }


    List<CFResultA> demo3_get() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<CompletableFuture<CFResultA>> completableFutures = list.stream().map(integer -> {
            CompletableFuture<CFResultA> completableFuture = CompletableFuture.supplyAsync(() -> {
                System.out.println("处理中......" + integer);
                if (integer == 1) {
                    int a = integer / 0;
                }
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return new CFResultA(integer);
            });
//            completableFuture.whenComplete((cfResult, throwable) -> {
//                System.out.println("cfResult"+cfResult+" throwable:"+throwable);
//            });
            return completableFuture;
        }).collect(Collectors.toList());

        //结果整理 CompletableFuture::get
        List<CFResultA> cfResultList = completableFutures.stream().map(cfResultCompletableFuture -> {
            try {
                return cfResultCompletableFuture.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList());
        return cfResultList;
    }


    List<CFResultB> demo4_thenApply() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<CompletableFuture<CFResultB>> completableFutures = list.stream()
                .map(integer -> {
                    CompletableFuture<CFResultA> completableFuture = CompletableFuture.supplyAsync(() -> {
                        System.out.println("处理中......" + integer);
                        try {
                            Thread.sleep(1000L);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        CFResultB cfResultB = new CFResultB(integer);
                        return new CFResultA(integer, cfResultB);
                    });
                    return completableFuture;
                })
                .map(future -> future.thenApply(this::dowork2))
                .collect(Collectors.toList());
        return completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
    }

    CFResultB dowork2(CFResultA cfResultA) {
        //todo thing
        return cfResultA.getCfResultB();
    }



    CompletableFuture<CFResultB> dowork(CFResultA cfResultA) {
        return  CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return cfResultA.getCfResultB();
        });
    }


    class CFResultA {
        private Integer cfParameter;
        private CFResultB cfResultB;

        public CFResultA(Integer cfParameter) {
            this.cfParameter = cfParameter;
        }

        public CFResultA(Integer cfParameter, CFResultB cfResultB) {
            this.cfParameter = cfParameter;
            this.cfResultB = cfResultB;
        }

        public Integer getCfParameter() {
            return cfParameter;
        }

        public void setCfParameter(Integer cfParameter) {
            this.cfParameter = cfParameter;
        }

        public CFResultB getCfResultB() {
            return cfResultB;
        }
    }

    class CFResultB {
        private Integer cfParameter;

        public CFResultB(Integer cfParameter) {
            this.cfParameter = cfParameter;
        }

        public Integer getCfParameter() {
            return cfParameter;
        }

        public void setCfParameter(Integer cfParameter) {
            this.cfParameter = cfParameter;
        }
    }


}
